﻿/*
* Copyright (C) 2020 ~ 2024 chaigec All Rights Reserved.
*
* Author:     chaigec <chaigec@163.com>
* Maintainer: chaigec <chaigec@163.com>

 * Use of this source code is governed by MIT license that can be found in the
 * LICENSE file in the root of the source tree. All contributing project authors
 * may be found in the AUTHORS file in the root of the source tree.
*/

#ifndef MK_GB28181_H
#define MK_GB28181_H
#include "MkGbUtil.h"
#include "MkSip/MkSipServer.h"
#include "MkUtil/MkTime.h"
#include "MkUtil/MkRwLock.h"
#include "MkUtil/MkLock.h"
#include <atomic>

typedef MkFunction<void(Uint32 ErrorCode, const CMkGbResponse* pGbRes)>  MkGbResponseCallback;
typedef MkFunction<Uint32(const CMkGbRequest* pGbReq, const MkGbResponseCallback& Cb)> MkGbRequestCallback;

typedef struct _gb_start_param
{
    MkString                SipId;
    MkString                SipRealm;
    MkString                LocalHost;
    Uint16                  LocalPort;
    MkString                MappingHost;  //can set empty
    Uint16                  MappingPort;  //can set 0
    Uint32                  RegisterExpires;      //register expires second
    Uint32                  SubscribeExpires;     //subscribe expires second
    BOOL                    bCheckDstId;    //check request to uri username and this sip id is same or not
    _gb_start_param()
    {
        SipId = "34020000002000000001";
        SipRealm = "3402000000";
        LocalPort = 5060;
        MappingPort = 0;
        RegisterExpires = 3600;
        SubscribeExpires = 3600;
        bCheckDstId = TRUE;
    }
}MkGbStartParam;

namespace tinyxml2
{
    class XMLElement;
    class XMLDocument;
}
class MkApi CMkGb28181 : public CMkSipServer
{
public:
    typedef MkFunction<void(Uint32 ErrorCode, const tinyxml2::XMLDocument& DocRes)>  MkGbCallback;

    typedef struct _gb_router
    {
        MkString    SipId;
        MkString    SipRealm;
        MkString    RemoteHost;
        Uint16      RemotePort;
        BOOL        bTcp;
    }MkGbRouter;

    typedef struct _request_param
    {
        //MkString                    strKey;
        MkGbResponseCallback                Cb;
        Uint32                              CurResponsed;  //has response count
        CMkTime                             RequestTime;
        _request_param()
        {
            CurResponsed = 0;
        }
    }MkGbRequestParam;

    typedef MkMap<MkString, MkGbRequestParam>  MapRequest;
public:
    CMkGb28181(CMkEventPool* pEventPool, CMkTimer* pTimer);
    virtual ~CMkGb28181();

    virtual Uint32 Start(const MkGbStartParam& Param, const MkGbRequestCallback& ReqCb/*,const MkGbAuthorReqCb& AuthorReqCb*/);
    Uint32 Stop();

    Uint32 MessageRequest(const CMkGbMessageRequest& Req, const MkGbResponseCallback& ResCb);
    Uint32 InviteMessageRequest(const CMkGbMessageRequest& Req, const MkString& CallId, const MkGbResponseCallback& ResCb);
    Uint32 SubscribeRequest(const CMkGbSubscribeRequest& Req, const MkGbResponseCallback& ResCb);
    Uint32 NotifyRequest(const CMkGbNotifyRequest& Req, const MkGbResponseCallback& ResCb);
    Uint32 RegisterRequest(const CMkGbDeviceAuthorRequest& Req, const MkGbResponseCallback& Cb);
    Uint32 InviteRequest(const MkString &RouterId, const MkString& ChannelId, const MkString& Subject, const MkString &OffserSdp, const MkGbResponseCallback &Cb);
    virtual Uint32 ByeRequest(const MkString &PlaySession, const MkGbResponseCallback &Cb);
    Uint32 InviteInfoRequest(const MkString& SessionId, const MkGbPlayControlType& ControlType, float fSleep, const Uint32& DragSecond, const MkGbResponseCallback &Cb);
    Uint32 AddRouter(const MkString& GbId, const MkString& GbRealm, const MkString& RemoteIp, Uint16 RemotePort, BOOL bTcp);
    Uint32 DeleteRouter(const MkString& GbId);
    Uint32 DoCheck();
private:
    Uint32 AddRequest(const MkString& strKey, const MkGbResponseCallback& Cb);
    virtual Uint32 OnSipRequest(const MkSipRequestEvent& RequestEvent, const CMkSipMessage& SipRequest, const EventRequestCallback& Cb) override;
    virtual Uint32 OnSipResponse(const MkSipResponseEvent& ResponseEvent, const MkString& TransActionId, const CMkSipMessage& SipRequest, const CMkSipMessage& SipResponse, const EventResponseCallback& Cb) override;
private:
    Uint32 RegisterRequestParse(const MkString& FromId, const MkString& DstId, const CMkSipMessage& SipRequest, const EventRequestCallback& EventCallback);
    Uint32 MessageRequestParse(const MkString& FromId, const MkString& DstId, const MkString& RequestBody, const EventRequestCallback& EventCallback);
    Uint32 InviteRequestParse(const MkString& FromId, const MkString& DstId, const CMkSipMessage& SipRequest, const EventRequestCallback& EventCallback);
    Uint32 SubscribeRequestParse(const MkString& FromId, const MkString& DstId, const CMkSipMessage& SipRequest, const EventRequestCallback& EventCallback);
    Uint32 InviteMessageRequestParse(const MkString& FromId, const MkString& DstId, const CMkSipMessage& SipRequest, const EventRequestCallback& EventCallback);
    Uint32 SubscribeNotifyRequestParse(const MkString& FromId, const MkString& DstId, const CMkSipMessage& SipRequest, const EventRequestCallback& EventCallback);
    Uint32 InviteInfoRequestParse(const MkString& FromId, const MkString& DstId, const CMkSipMessage& SipRequest, const EventRequestCallback& EventCallback);
    Uint32 ByeRequestParse(const MkString& FromId, const MkString& DstId, const CMkSipMessage& SipRequest, const EventRequestCallback& EventCallback);
    Uint32 AckRequestParse(const MkString& FromId, const MkString& DstId, const CMkSipMessage& SipRequest, const EventRequestCallback& EventCallback);
    Uint32 ResponseInviteParse(const CMkSipMessage& SipRequest, const CMkSipMessage& SipResponse, const EventResponseCallback& Cb);
    Uint32 ResponseSubscribeParse(const CMkSipMessage& SipRequest, const CMkSipMessage& SipResponse);
    Uint32 ResponseRegisterParse(const CMkSipMessage& SipRequest, const CMkSipMessage& SipResponse);
    Uint32 ResponseMessageParse(const CMkSipMessage& SipRequest, const CMkSipMessage& SipResponse);
    Uint32 ResponseMessageQueryParse(const tinyxml2::XMLElement* pElement, const CMkSipMessage& SipRequest, const CMkSipMessage& SipResponse);
    Uint32 ResponseMessageControlParse(const tinyxml2::XMLElement* pElement, const CMkSipMessage& SipRequest, const CMkSipMessage& SipResponse);

    Uint32 MessageResponseParse(const tinyxml2::XMLElement *pElement, const EventRequestCallback& EventCallback);
    Uint32 MessageGbRequestParse(const MkString& FromId, const MkString& DstId, const MkString& MessageType, const tinyxml2::XMLElement *pElement, const EventRequestCallback& EventCallback);

    Uint32 SendMessageResponse(const MkString& RouterId, const MkString& DstId, const MkString& DeviceId, const MkString& StrSn, const MkString& CmdType, const CMkGbMessageResponse& Res);


    Uint32 XmlItemParse(const tinyxml2::XMLElement *pElement, MkMapString &MapParam);
    Uint32 XmlToGbMessage(const tinyxml2::XMLElement *pElement, MkGbMessage& GbMessage);
    Uint32 MapStringToXml(const MkMapString& MapParam, tinyxml2::XMLDocument& doc, tinyxml2::XMLElement *pParentElement);
    Uint32 GbMessageToXml(const MkGbMessage& GbMessage, tinyxml2::XMLDocument& doc, tinyxml2::XMLElement *pParentElement, Uint32 SumChild = 0);

    Uint32 RequestCheck();
    Uint32 GbResponseCallback(Uint32 ErrorCode, const MkString& strKey, const CMkGbResponse* pRes);

    Uint32 GetRouter(const MkString& GbId, MkGbRouter& Router);
private:
    Uint32                          m_RegisterExpries;
    Uint32                          m_SubscribeExpires;
    MkGbRequestCallback             m_ReqCb;
    std::atomic<Uint16>             m_Sn;
    MkVectorString                  m_SupportQueryCmd;

    CMkRwLock                       m_RouterLock;
    MkMap<MkString, MkGbRouter>     m_MapGbRouter; //key gb id include device and up server

    CMkLock                         m_RequestLock;
    MapRequest                      m_MapRequest;

    MkString                        m_CheckTimer;
    Uint32                          m_CheckOffsetMilliSec;
    Uint32                          m_RequestTimeOutSec;
    BOOL                            m_bCheckDstId;
};






#endif
